#include "npc.h"
#include "functions.h"
#include "globals.h"
#include "config.h"
#include "SDL/SDL_ttf.h"

std::map<int, Npc*> Npc::Npcs;

Npc::Npc(int id, std::string name, int x, int y)
{
    Npcs.insert(std::pair<int, Npc*>(id, this));

    box.x = x;
    box.y = y;
    box.w = 32;
    box.h = 32;

    this->id = id;
    this->name = name;

    pos.x = x;
    pos.y = y;
    flag.x = -1;
    flag.y = -1;
    velX = 0;
    velY = 0;
    dir = DIR_UP;
    movementSpeed = 256;

    set_clips();
    nameText = TTF_RenderText_Solid(font, name.c_str(), textColor);
}

Npc::~Npc()
{
    SDL_FreeSurface(nameText);

    Npcs.erase(this->id);
}

Npc* Npc::GetNpcFromID(int id)
{
    std::map<int, Npc*>::iterator i;
    i = Npcs.find(id);

    if (i != Npcs.end())
        return i->second;

    return NULL;
}

std::map<int, Npc*> Npc::GetNpcList()
{
    return Npcs;
}

Npc* Npc::GetNpcOnPosition(int posX, int posY)
{
    for (std::map<int, Npc*>::iterator i = Npcs.begin(); i != Npcs.end(); i++)
    {
        Npc* npc = i->second;
        SDL_Rect boxNpc = npc->get_box();

        if ((posX > boxNpc.x) and (posX < boxNpc.x + boxNpc.w) and (posY > boxNpc.y) and (posY < boxNpc.y + boxNpc.h))
        {
            return npc;
        }
    }

    return NULL;
}

void Npc::removeNpcs()
{
    Npcs.clear();
}

void Npc::create_flag(int x, int y)
{
    flag.x = x;
    flag.y = y;

    calculate_vel();
    dir = calculate_dir(pos.x, pos.y, flag.x, flag.y);
}

void Npc::stop()
{
    flag.x = -1;
    flag.y = -1;

    velX = 0;
    velY = 0;
}

void Npc::move(Uint32 deltaTicks)
{
    /*if (pos.x < 64)
    {
        //output->write("Travel west!");
        pos.x = 64;
    }

    if (pos.x + 64 > cfg.get_map_width())
    {
        //output->write("Travel east!");
        pos.x = cfg.get_map_width() - 64;
    }

    if (pos.y < 64)
    {
        //output->write("Travel north!");
        pos.y = 64;
    }

    if (pos.y + 64 > cfg.get_map_height())
    {
        //output->write("Travel south!");
        pos.y = cfg.get_map_width() - 64;
    }

    update_rect();*/

    if (flag.x != -1 && flag.y != -1)
    {
        if (pos.x != flag.x)
        {
            pos.x += (deltaTicks / 1000.f) * velX;

            if (velX > 0)
            {
                if (pos.x > flag.x)
                {
                    pos.x = flag.x;
                }
            }
            else
            {
                if (pos.x < flag.x)
                {
                    pos.x = flag.x;
                }
            }
        }

        if (pos.y != flag.y)
        {
            pos.y += (deltaTicks / 1000.f) * velY;

            if (velY > 0)
            {
                if (pos.y > flag.y)
                {
                    pos.y = flag.y;
                }
            }
            else
            {
                if (pos.y < flag.y)
                {
                    pos.y = flag.y;
                }
            }
        }

        if ((pos.x == flag.x) and (pos.y == flag.y))
        {
            stop();
        }

        update_rect();
    }
}

void Npc::calculate_vel()
{
    velX = movementSpeed * (flag.x - pos.x) / distance(pos.x, pos.y, flag.x, flag.y);
    velY = movementSpeed * (flag.y - pos.y) / distance(pos.x, pos.y, flag.x, flag.y);
}

void Npc::update_rect()
{
    box.x = pos.x - box.w / 2.f;
    box.y = pos.y - box.h / 2.f;
}

void Npc::set_clips()
{
    //Clip the sprites

    myClip[DIR_RIGHTUP].x = box.w * 0;
    myClip[DIR_RIGHTUP].y = 0;
    myClip[DIR_RIGHTUP].w = box.w;
    myClip[DIR_RIGHTUP].h = box.h;

    myClip[DIR_RIGHT].x = box.w * 1;
    myClip[DIR_RIGHT].y = 0;
    myClip[DIR_RIGHT].w = box.w;
    myClip[DIR_RIGHT].h = box.h;

    myClip[DIR_RIGHTDOWN].x = box.w * 2;
    myClip[DIR_RIGHTDOWN].y = 0;
    myClip[DIR_RIGHTDOWN].w = box.w;
    myClip[DIR_RIGHTDOWN].h = box.h;

    myClip[DIR_DOWN].x = box.w * 3;
    myClip[DIR_DOWN].y = 0;
    myClip[DIR_DOWN].w = box.w;
    myClip[DIR_DOWN].h = box.h;

    myClip[DIR_LEFTDOWN].x = box.w * 4;
    myClip[DIR_LEFTDOWN].y = 0;
    myClip[DIR_LEFTDOWN].w = box.w;
    myClip[DIR_LEFTDOWN].h = box.h;

    myClip[DIR_LEFT].x = box.w * 5;
    myClip[DIR_LEFT].y = 0;
    myClip[DIR_LEFT].w = box.w;
    myClip[DIR_LEFT].h = box.h;

    myClip[DIR_LEFTUP].x = box.w * 6;
    myClip[DIR_LEFTUP].y = 0;
    myClip[DIR_LEFTUP].w = box.w;
    myClip[DIR_LEFTUP].h = box.h;

    myClip[DIR_UP].x = box.w * 7;
    myClip[DIR_UP].y = 0;
    myClip[DIR_UP].w = box.w;
    myClip[DIR_UP].h = box.h;
}

int Npc::get_id()
{
    return id;
}

void Npc::set_x(int dest_x)
{
    pos.x = dest_x;
    update_rect();
}

void Npc::set_y(int dest_y)
{
    pos.y = dest_y;
    update_rect();
}

int Npc::x()
{
    return (int)pos.x;
}

int Npc::y()
{
    return (int)pos.y;
}

std::string Npc::get_name()
{
    return name;
}

SDL_Rect Npc::get_box()
{
    return box;
}

void Npc::draw()
{
    apply_surface(box.x, box.y, imgNpc, screen, &myClip[dir]);
    apply_surface(pos.x- (nameText->w / 2), pos.y - (nameText->h / 2) - box.h, nameText, screen);
    if (debug)
        draw_box(box.x, box.y, box.w, box.h, 0xFF0000FF, false);
}
